11/* eslint-disable no-console */
2+ import * as ts from 'typescript' ;
23import { promises as fs } from 'fs' ;
34import path from 'path' ;
45import { replaceImports } from '../src/utils' ;
56
67async function loadSources ( sources : Record < string , string > ) {
7- const result : Record < string , string > = { } ;
8+ const result : Record < string , string | true > = { } ;
89
9- for ( const [ key , filepath ] of Object . entries ( sources ) ) {
10- result [ key ] = replaceImports ( await fs . readFile ( filepath , 'utf8' ) ) ;
10+ for ( const [ key , filePath ] of Object . entries ( sources ) ) {
11+ // for .js filepaths we're never going to read them, so just make the
12+ // value true as an optimisation so we can still know that they should
13+ // exist during the language server's module resolution.
14+ try {
15+ const data = filePath . endsWith ( '.js' )
16+ ? true
17+ : replaceImports ( await fs . readFile ( filePath , 'utf8' ) ) ;
18+ result [ key ] = data ;
19+ } catch ( err : any ) {
20+ if ( err . code !== 'ENOENT' ) {
21+ console . error ( `Error reading file ${ filePath } :` , err ) ;
22+ throw err ;
23+ }
24+ }
1125 }
1226
1327 return result ;
1428}
1529
30+ function resolve ( moduleName : string ) {
31+ const result = ts . resolveModuleName (
32+ moduleName ,
33+ __filename ,
34+ { } ,
35+ {
36+ fileExists : ( path : string ) => ts . sys . fileExists ( path ) ,
37+ readFile : ( path : string ) => ts . sys . readFile ( path ) ,
38+ } ,
39+ ) ;
40+
41+ return result ;
42+ }
43+
44+ const deps : Record < string , string [ ] > = {
45+ '@mongodb-js/mongodb-ts-autocomplete' : [
46+ // the module resolution won't be addressing this module by name, but we'll
47+ // feed it this package.json as a fallback when it tries to find itself
48+ 'package.json' ,
49+ ] ,
50+ '@types/node' : [
51+ 'package.json' ,
52+ 'assert.d.ts' ,
53+ 'assert/strict.d.ts' ,
54+ 'async_hooks.d.ts' ,
55+ 'buffer.buffer.d.ts' ,
56+ 'buffer.d.ts' ,
57+ 'child_process.d.ts' ,
58+ 'cluster.d.ts' ,
59+ 'compatibility/disposable.d.ts' ,
60+ 'compatibility/index.d.ts' ,
61+ 'compatibility/indexable.d.ts' ,
62+ 'compatibility/iterators.d.ts' ,
63+ 'console.d.ts' ,
64+ 'constants.d.ts' ,
65+ 'crypto.d.ts' ,
66+ 'dgram.d.ts' ,
67+ 'diagnostics_channel.d.ts' ,
68+ 'dns.d.ts' ,
69+ 'dns/promises.d.ts' ,
70+ 'dom-events.d.ts' ,
71+ 'domain.d.ts' ,
72+ 'events.d.ts' ,
73+ 'fs.d.ts' ,
74+ 'fs/promises.d.ts' ,
75+ 'globals.d.ts' ,
76+ 'globals.typedarray.d.ts' ,
77+ 'http.d.ts' ,
78+ 'http2.d.ts' ,
79+ 'https.d.ts' ,
80+ 'index.d.ts' ,
81+ 'inspector.d.ts' ,
82+ 'module.d.ts' ,
83+ 'net.d.ts' ,
84+ 'os.d.ts' ,
85+ 'path.d.ts' ,
86+ 'perf_hooks.d.ts' ,
87+ 'process.d.ts' ,
88+ 'punycode.d.ts' ,
89+ 'querystring.d.ts' ,
90+ 'readline.d.ts' ,
91+ 'readline/promises.d.ts' ,
92+ 'repl.d.ts' ,
93+ 'sea.d.ts' ,
94+ 'sqlite.d.ts' ,
95+ 'stream.d.ts' ,
96+ 'stream/consumers.d.ts' ,
97+ 'stream/promises.d.ts' ,
98+ 'stream/web.d.ts' ,
99+ 'string_decoder.d.ts' ,
100+ 'test.d.ts' ,
101+ 'timers.d.ts' ,
102+ 'timers/promises.d.ts' ,
103+ 'tls.d.ts' ,
104+ 'trace_events.d.ts' ,
105+ 'tty.d.ts' ,
106+ 'url.d.ts' ,
107+ 'util.d.ts' ,
108+ 'v8.d.ts' ,
109+ 'vm.d.ts' ,
110+ 'wasi.d.ts' ,
111+ 'worker_threads.d.ts' ,
112+ 'zlib.d.ts' ,
113+ ] ,
114+ assert : [
115+ 'package.json' ,
116+ 'assert.js' , // exists only
117+ ] ,
118+ buffer : [ 'package.json' , 'index.d.ts' ] ,
119+ events : [ 'package.json' ] ,
120+ punycode : [
121+ 'package.json' ,
122+ 'punycode.js' , // exists only
123+ ] ,
124+ querystring : [
125+ 'package.json' ,
126+ 'index.js' , // exists only
127+ ] ,
128+ string_decoder : [
129+ 'package.json' ,
130+ 'lib/string_decoder.js' , // exists only
131+ ] ,
132+ typescript : [
133+ 'package.json' ,
134+ 'lib/es2023.ts' ,
135+ 'lib/lib.decorators.d.ts' ,
136+ 'lib/lib.decorators.legacy.d.ts' ,
137+ 'lib/lib.es2015.collection.d.ts' ,
138+ 'lib/lib.es2015.core.d.ts' ,
139+ 'lib/lib.es2015.d.ts' ,
140+ 'lib/lib.es2015.generator.d.ts' ,
141+ 'lib/lib.es2015.iterable.d.ts' ,
142+ 'lib/lib.es2015.promise.d.ts' ,
143+ 'lib/lib.es2015.proxy.d.ts' ,
144+ 'lib/lib.es2015.reflect.d.ts' ,
145+ 'lib/lib.es2015.symbol.d.ts' ,
146+ 'lib/lib.es2015.symbol.wellknown.d.ts' ,
147+ 'lib/lib.es2016.array.include.d.ts' ,
148+ 'lib/lib.es2016.d.ts' ,
149+ 'lib/lib.es2016.intl.d.ts' ,
150+ 'lib/lib.es2017.arraybuffer.d.ts' ,
151+ 'lib/lib.es2017.d.ts' ,
152+ 'lib/lib.es2017.date.d.ts' ,
153+ 'lib/lib.es2017.intl.d.ts' ,
154+ 'lib/lib.es2017.object.d.ts' ,
155+ 'lib/lib.es2017.sharedmemory.d.ts' ,
156+ 'lib/lib.es2017.string.d.ts' ,
157+ 'lib/lib.es2017.typedarrays.d.ts' ,
158+ 'lib/lib.es2018.asyncgenerator.d.ts' ,
159+ 'lib/lib.es2018.asynciterable.d.ts' ,
160+ 'lib/lib.es2018.d.ts' ,
161+ 'lib/lib.es2018.intl.d.ts' ,
162+ 'lib/lib.es2018.promise.d.ts' ,
163+ 'lib/lib.es2018.regexp.d.ts' ,
164+ 'lib/lib.es2019.array.d.ts' ,
165+ 'lib/lib.es2019.d.ts' ,
166+ 'lib/lib.es2019.intl.d.ts' ,
167+ 'lib/lib.es2019.object.d.ts' ,
168+ 'lib/lib.es2019.string.d.ts' ,
169+ 'lib/lib.es2019.symbol.d.ts' ,
170+ 'lib/lib.es2020.bigint.d.ts' ,
171+ 'lib/lib.es2020.d.ts' ,
172+ 'lib/lib.es2020.date.d.ts' ,
173+ 'lib/lib.es2020.intl.d.ts' ,
174+ 'lib/lib.es2020.number.d.ts' ,
175+ 'lib/lib.es2020.promise.d.ts' ,
176+ 'lib/lib.es2020.sharedmemory.d.ts' ,
177+ 'lib/lib.es2020.string.d.ts' ,
178+ 'lib/lib.es2020.symbol.wellknown.d.ts' ,
179+ 'lib/lib.es5.d.ts' ,
180+ ] ,
181+ 'undici-types' : [ 'package.json' , 'index.d.ts' ] ,
182+ url : [
183+ 'package.json' ,
184+ 'url.js' , // exists only
185+ ] ,
186+ util : [
187+ 'package.json' ,
188+ 'util.js' , // exists only
189+ ] ,
190+ } ;
191+
16192async function run ( ) {
193+ // TODO: switch require.resolve() to resolve()
17194 const input : Record < string , string > = {
18195 // mql imports bson but right now so does shell-api. We could bake the types
19196 // those use into the files we generate using api-extractor, but maybe
@@ -38,6 +215,25 @@ async function run() {
38215 'schema.d.ts' ,
39216 ) ,
40217 } ;
218+ for ( const [ moduleName , filePaths ] of Object . entries ( deps ) ) {
219+ const { resolvedModule } = resolve ( moduleName ) ;
220+ if ( ! resolvedModule || ! resolvedModule . packageId ) {
221+ throw new Error ( `Could not resolve module: ${ moduleName } ` ) ;
222+ }
223+
224+ const basePath = resolvedModule . resolvedFileName . slice (
225+ 0 ,
226+ - resolvedModule . packageId . subModuleName . length ,
227+ ) ;
228+ //console.log({ basePath});
229+ for ( const filePath of filePaths ) {
230+ const fullPath = path . join ( basePath , filePath ) ;
231+ //console.log({ fullPath });
232+ // these are in the format import of typescript imports
233+ input [ `${ moduleName } /${ filePath } ` ] = fullPath ;
234+ }
235+ }
236+
41237 const files = await loadSources ( input ) ;
42238 const code = `
43239const files = ${ JSON . stringify ( files ) } ;
0 commit comments