@ts-for-gir/cli 4.0.0-beta.9 → 4.0.0-rc.10
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/README.md +335 -86
- package/bin/ts-for-gir +28832 -0
- package/bin/ts-for-gir-dev +43 -0
- package/bin/ts-for-gir-gjs +348955 -0
- package/dist-templates/types-locally/.ts-for-girrc.js +6 -0
- package/dist-templates/types-locally/README.md +15 -0
- package/dist-templates/types-locally/esbuild.ts +10 -0
- package/dist-templates/types-locally/main.ts +21 -0
- package/dist-templates/types-locally/package.json +18 -0
- package/dist-templates/types-locally/tsconfig.json +17 -0
- package/dist-templates/types-npm/README.md +14 -0
- package/dist-templates/types-npm/esbuild.ts +10 -0
- package/dist-templates/types-npm/main.ts +19 -0
- package/dist-templates/types-npm/package.json +23 -0
- package/dist-templates/types-npm/tsconfig.json +15 -0
- package/dist-templates/types-workspace/.ts-for-girrc.js +12 -0
- package/dist-templates/types-workspace/README.md +26 -0
- package/dist-templates/types-workspace/package.json +22 -0
- package/dist-templates/types-workspace/packages/app/esbuild.ts +10 -0
- package/dist-templates/types-workspace/packages/app/main.ts +19 -0
- package/dist-templates/types-workspace/packages/app/package.json +23 -0
- package/dist-templates/types-workspace/packages/app/tsconfig.json +15 -0
- package/dist-templates/types-workspace/tsconfig.json +11 -0
- package/package.json +60 -37
- package/src/commands/analyze.ts +344 -0
- package/src/commands/command-builder.ts +30 -0
- package/src/commands/copy.ts +71 -76
- package/src/commands/create.ts +223 -0
- package/src/commands/doc.ts +44 -47
- package/src/commands/generate.ts +35 -79
- package/src/commands/index.ts +8 -4
- package/src/commands/json.ts +43 -0
- package/src/commands/list.ts +71 -90
- package/src/commands/run-generation-command.ts +75 -0
- package/src/commands/self-update.ts +142 -0
- package/src/config/config-loader.ts +238 -0
- package/src/config/config-writer.ts +52 -0
- package/src/config/defaults.ts +68 -0
- package/src/config/index.ts +16 -0
- package/src/config/options.ts +365 -0
- package/src/config.ts +3 -456
- package/src/formatters/typescript-formatter.ts +17 -0
- package/src/generation-handler.ts +122 -67
- package/src/index.ts +4 -4
- package/src/module-loader/dependency-resolver.ts +100 -0
- package/src/module-loader/file-finder.ts +65 -0
- package/src/module-loader/index.ts +8 -0
- package/src/module-loader/module-grouper.ts +77 -0
- package/src/module-loader/prompt-handler.ts +111 -0
- package/src/module-loader.ts +321 -578
- package/src/start.ts +36 -15
- package/src/types/command-args.ts +154 -0
- package/src/types/command-definition.ts +17 -0
- package/src/types/commands.ts +30 -0
- package/src/types/index.ts +15 -0
- package/src/types/report-types.ts +34 -0
- package/lib/commands/copy.d.ts +0 -12
- package/lib/commands/copy.js +0 -80
- package/lib/commands/copy.js.map +0 -1
- package/lib/commands/doc.d.ts +0 -12
- package/lib/commands/doc.js +0 -40
- package/lib/commands/doc.js.map +0 -1
- package/lib/commands/generate.d.ts +0 -12
- package/lib/commands/generate.js +0 -71
- package/lib/commands/generate.js.map +0 -1
- package/lib/commands/index.d.ts +0 -4
- package/lib/commands/index.js +0 -5
- package/lib/commands/index.js.map +0 -1
- package/lib/commands/list.d.ts +0 -12
- package/lib/commands/list.js +0 -81
- package/lib/commands/list.js.map +0 -1
- package/lib/config.d.ts +0 -108
- package/lib/config.js +0 -410
- package/lib/config.js.map +0 -1
- package/lib/generation-handler.d.ts +0 -10
- package/lib/generation-handler.js +0 -48
- package/lib/generation-handler.js.map +0 -1
- package/lib/index.d.ts +0 -4
- package/lib/index.js +0 -5
- package/lib/index.js.map +0 -1
- package/lib/module-loader.d.ts +0 -148
- package/lib/module-loader.js +0 -468
- package/lib/module-loader.js.map +0 -1
- package/lib/start.d.ts +0 -2
- package/lib/start.js +0 -16
- package/lib/start.js.map +0 -1
package/src/module-loader.ts
CHANGED
|
@@ -2,585 +2,328 @@
|
|
|
2
2
|
* The ModuleLoader is used for reading gir modules from the file system and to solve conflicts (e.g. Gtk-3.0 and Gtk-4.0 would be a conflict)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import inquirer, { ListQuestion, Answers } from 'inquirer'
|
|
6
|
-
import { glob } from 'glob'
|
|
7
|
-
import { basename, join } from 'path'
|
|
8
|
-
import { bold } from 'colorette'
|
|
9
|
-
import {
|
|
10
|
-
DependencyManager,
|
|
11
|
-
ResolveType,
|
|
12
|
-
GirModule,
|
|
13
|
-
Logger,
|
|
14
|
-
splitModuleName,
|
|
15
|
-
union,
|
|
16
|
-
isIterable,
|
|
17
|
-
WARN_NO_GIR_FILE_FOUND_FOR_PACKAGE,
|
|
18
|
-
} from '@ts-for-gir/lib'
|
|
19
|
-
import { Config } from './config.js'
|
|
20
|
-
|
|
21
5
|
import type {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
6
|
+
AnswerVersion,
|
|
7
|
+
Dependency,
|
|
8
|
+
GirModuleResolvedBy,
|
|
9
|
+
GirModulesGroupedMap,
|
|
10
|
+
NSRegistry,
|
|
11
|
+
OptionsGeneration,
|
|
12
|
+
} from "@ts-for-gir/lib";
|
|
13
|
+
import {
|
|
14
|
+
DependencyManager,
|
|
15
|
+
GirModule,
|
|
16
|
+
Logger,
|
|
17
|
+
ResolveType,
|
|
18
|
+
union,
|
|
19
|
+
WARN_NO_GIR_FILE_FOUND_FOR_PACKAGE,
|
|
20
|
+
} from "@ts-for-gir/lib";
|
|
21
|
+
import { DependencyResolver, FileFinder, ModuleGrouper, PromptHandler } from "./module-loader/index.ts";
|
|
30
22
|
|
|
31
23
|
export class ModuleLoader {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
protected traverseDependencies(packageName: string, result: { [name: string]: Dependency } = {}): void {
|
|
338
|
-
const deps = this.modDependencyMap[packageName]
|
|
339
|
-
if (isIterable(deps)) {
|
|
340
|
-
for (const dep of deps) {
|
|
341
|
-
if (result[dep.packageName]) continue
|
|
342
|
-
result[dep.packageName] = dep
|
|
343
|
-
this.traverseDependencies(dep.packageName, result)
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Extends the modDependencyMap by the current Module,
|
|
350
|
-
* should be called for each girModule so that the modDependencyMap is complete
|
|
351
|
-
* @param girModule
|
|
352
|
-
*/
|
|
353
|
-
protected extendDependencyMapByGirModule(girModule: GirModule): void {
|
|
354
|
-
this.modDependencyMap[girModule.packageName] = girModule.dependencies!
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Sets the traverse dependencies for the current girModule,
|
|
359
|
-
* is required so that all dependencies can be found internally when generating the dependency imports for the module .d.ts file
|
|
360
|
-
* @param girModules
|
|
361
|
-
*/
|
|
362
|
-
protected async initGirModules(girModules: GirModuleResolvedBy[]): Promise<void> {
|
|
363
|
-
for (const girModule of girModules) {
|
|
364
|
-
const result: { [name: string]: Dependency } = {}
|
|
365
|
-
this.traverseDependencies(girModule.packageName, result)
|
|
366
|
-
await girModule.module.initTransitiveDependencies(Object.values(result))
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Reads a gir xml module file and creates an object of GirModule.
|
|
372
|
-
* Also sets the setDependencyMap
|
|
373
|
-
* @param fillName
|
|
374
|
-
* @param config
|
|
375
|
-
*/
|
|
376
|
-
protected async loadAndCreateGirModule(dependency: Dependency): Promise<GirModule | null> {
|
|
377
|
-
if (!dependency.exists || dependency.path === null) {
|
|
378
|
-
return null
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
this.log.log(`Loading ${dependency.packageName}...`)
|
|
382
|
-
const girModule = await GirModule.load(dependency, this.config, this.dependencyManager)
|
|
383
|
-
// Figure out transitive module dependencies
|
|
384
|
-
this.extendDependencyMapByGirModule(girModule)
|
|
385
|
-
return girModule
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Returns a girModule found by `packageName` property
|
|
390
|
-
* @param girModules Array of girModules
|
|
391
|
-
* @param packageNames Full name like 'Gtk-3.0' you are looking for
|
|
392
|
-
*/
|
|
393
|
-
protected findGirModuleByFullNames(
|
|
394
|
-
girModules: (GirModuleResolvedBy | GirModule)[],
|
|
395
|
-
packageNames: string[],
|
|
396
|
-
): Array<GirModuleResolvedBy | GirModule> {
|
|
397
|
-
return girModules.filter((girModule) => packageNames.includes(girModule.packageName))
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Checks if a girModules with the `packageNames` exists
|
|
402
|
-
* @param girModules
|
|
403
|
-
* @param packageName
|
|
404
|
-
*/
|
|
405
|
-
protected existsGirModules(girModules: (GirModuleResolvedBy | GirModule)[], packageName: string): boolean {
|
|
406
|
-
const foundModule = this.findGirModuleByFullNames(girModules, [packageName])
|
|
407
|
-
return foundModule.length > 0
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* Reads the gir xml module files and creates an object of GirModule for each module
|
|
412
|
-
* @param dependencies
|
|
413
|
-
* @param girModules
|
|
414
|
-
* @param resolvedBy
|
|
415
|
-
* @param failedGirModules
|
|
416
|
-
* @param ignoreDependencies
|
|
417
|
-
* @returns
|
|
418
|
-
*/
|
|
419
|
-
protected async loadGirModules(
|
|
420
|
-
dependencies: Dependency[],
|
|
421
|
-
ignoreDependencies: string[] = [],
|
|
422
|
-
girModules: GirModuleResolvedBy[] = [],
|
|
423
|
-
resolvedBy = ResolveType.BY_HAND,
|
|
424
|
-
failedGirModules = new Set<string>(),
|
|
425
|
-
): Promise<{ loaded: GirModuleResolvedBy[]; failed: Set<string> }> {
|
|
426
|
-
let newModuleFound = false
|
|
427
|
-
|
|
428
|
-
// Clone array
|
|
429
|
-
dependencies = [...dependencies]
|
|
430
|
-
|
|
431
|
-
while (dependencies.length > 0) {
|
|
432
|
-
const dependency = dependencies.shift()
|
|
433
|
-
if (!dependency?.packageName) continue
|
|
434
|
-
// If module has not already been loaded
|
|
435
|
-
if (!this.existsGirModules(girModules, dependency.packageName)) {
|
|
436
|
-
const girModule = await this.loadAndCreateGirModule(dependency)
|
|
437
|
-
if (!girModule) {
|
|
438
|
-
if (!failedGirModules.has(dependency.packageName)) {
|
|
439
|
-
this.log.warn(WARN_NO_GIR_FILE_FOUND_FOR_PACKAGE(dependency.packageName))
|
|
440
|
-
failedGirModules.add(dependency.packageName)
|
|
441
|
-
}
|
|
442
|
-
} else if (girModule && girModule.packageName) {
|
|
443
|
-
const addModule = {
|
|
444
|
-
packageName: girModule.packageName,
|
|
445
|
-
module: girModule,
|
|
446
|
-
resolvedBy,
|
|
447
|
-
path: dependency.path,
|
|
448
|
-
}
|
|
449
|
-
girModules.push(addModule)
|
|
450
|
-
newModuleFound = true
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (!newModuleFound) {
|
|
456
|
-
return {
|
|
457
|
-
loaded: girModules,
|
|
458
|
-
failed: failedGirModules,
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// Figure out transitive module dependencies
|
|
463
|
-
await this.initGirModules(girModules)
|
|
464
|
-
|
|
465
|
-
// Load girModules for dependencies
|
|
466
|
-
for (const girModule of girModules) {
|
|
467
|
-
// Load dependencies
|
|
468
|
-
const transitiveDependencies = girModule.module.transitiveDependencies
|
|
469
|
-
if (transitiveDependencies.length > 0) {
|
|
470
|
-
await this.loadGirModules(
|
|
471
|
-
transitiveDependencies,
|
|
472
|
-
ignoreDependencies,
|
|
473
|
-
girModules,
|
|
474
|
-
ResolveType.DEPENDENCE,
|
|
475
|
-
failedGirModules,
|
|
476
|
-
)
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
return {
|
|
481
|
-
loaded: girModules,
|
|
482
|
-
failed: failedGirModules,
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* Find modules with the possibility to use wild cards for module names. E.g. `Gtk*` or `'*'`
|
|
488
|
-
* @param modules
|
|
489
|
-
* @param ignore
|
|
490
|
-
*/
|
|
491
|
-
protected async findGirFiles(globPackageNames: string[], ignore: string[] = []): Promise<Set<string>> {
|
|
492
|
-
const foundFiles = new Set<string>()
|
|
493
|
-
|
|
494
|
-
for (let i = 0; i < globPackageNames.length; i++) {
|
|
495
|
-
if (!globPackageNames[i]) {
|
|
496
|
-
continue
|
|
497
|
-
}
|
|
498
|
-
const filename = `${globPackageNames[i]}.gir`
|
|
499
|
-
const pattern = this.config.girDirectories.map((girDirectory) => join(girDirectory, filename))
|
|
500
|
-
const ignoreGirs = ignore.map((girDirectory) => girDirectory + '.gir')
|
|
501
|
-
const files = await glob(pattern, { ignore: ignoreGirs })
|
|
502
|
-
files.forEach((file) => foundFiles.add(file))
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
return foundFiles
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
protected async girFilePathToDependencies(girFiles: Set<string>): Promise<Dependency[]> {
|
|
509
|
-
const dependencies: Dependency[] = []
|
|
510
|
-
for (const girFile of girFiles) {
|
|
511
|
-
const packageName = basename(girFile, '.gir')
|
|
512
|
-
const { namespace, version } = splitModuleName(packageName)
|
|
513
|
-
const dep = await this.dependencyManager.get(namespace, version)
|
|
514
|
-
dependencies.push(dep)
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
return dependencies
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
/**
|
|
521
|
-
* Loads all found `packageNames`
|
|
522
|
-
* @param girDirectories
|
|
523
|
-
* @param packageNames
|
|
524
|
-
* @param doNotAskForVersionOnConflict Set this to false if you want to get a prompt for each version conflict
|
|
525
|
-
*/
|
|
526
|
-
public async getModulesResolved(
|
|
527
|
-
packageNames: string[],
|
|
528
|
-
ignore: string[] = [],
|
|
529
|
-
doNotAskForVersionOnConflict = true,
|
|
530
|
-
): Promise<{ keep: GirModuleResolvedBy[]; grouped: GirModulesGroupedMap; ignore: string[]; failed: Set<string> }> {
|
|
531
|
-
const girFiles = await this.findGirFiles([...packageNames], ignore)
|
|
532
|
-
// Always require these because GJS does...
|
|
533
|
-
const GLib = await this.dependencyManager.get('GLib', '2.0')
|
|
534
|
-
const Gio = await this.dependencyManager.get('Gio', '2.0')
|
|
535
|
-
const GObject = await this.dependencyManager.get('GObject', '2.0')
|
|
536
|
-
|
|
537
|
-
const dependencies = await this.girFilePathToDependencies(girFiles)
|
|
538
|
-
|
|
539
|
-
const { loaded, failed } = await this.loadGirModules(
|
|
540
|
-
[
|
|
541
|
-
GLib,
|
|
542
|
-
Gio,
|
|
543
|
-
GObject,
|
|
544
|
-
...dependencies.filter(
|
|
545
|
-
(dep) => dep.namespace !== 'GLib' && dep.namespace !== 'Gio' && dep.namespace !== 'GObject',
|
|
546
|
-
),
|
|
547
|
-
],
|
|
548
|
-
ignore,
|
|
549
|
-
)
|
|
550
|
-
let keep: GirModuleResolvedBy[] = []
|
|
551
|
-
if (doNotAskForVersionOnConflict) {
|
|
552
|
-
keep = loaded
|
|
553
|
-
} else {
|
|
554
|
-
const girModulesGrouped = this.groupGirFiles(loaded)
|
|
555
|
-
const filtered = await this.askForEachConflictVersionsPrompt(girModulesGrouped, ignore)
|
|
556
|
-
keep = Array.from(filtered.keep)
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
const grouped = this.groupGirFiles(keep)
|
|
560
|
-
|
|
561
|
-
return { keep, grouped, ignore, failed }
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
/**
|
|
565
|
-
* Find modules
|
|
566
|
-
* @param girDirectories
|
|
567
|
-
* @param modules
|
|
568
|
-
*/
|
|
569
|
-
public async getModules(
|
|
570
|
-
modules: string[],
|
|
571
|
-
ignore: string[] = [],
|
|
572
|
-
): Promise<{ grouped: GirModulesGroupedMap; loaded: GirModuleResolvedBy[]; failed: string[] }> {
|
|
573
|
-
const girFiles = await this.findGirFiles(modules, ignore)
|
|
574
|
-
const dependencies = await this.girFilePathToDependencies(girFiles)
|
|
575
|
-
const { loaded, failed } = await this.loadGirModules(dependencies, ignore)
|
|
576
|
-
const grouped = this.groupGirFiles(loaded)
|
|
577
|
-
return { grouped, loaded, failed: Array.from(failed) }
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
/** Start parsing the gir modules */
|
|
581
|
-
public parse(girModules: GirModuleResolvedBy[]): void {
|
|
582
|
-
for (const girModule of girModules) {
|
|
583
|
-
girModule.module.parse()
|
|
584
|
-
}
|
|
585
|
-
}
|
|
24
|
+
private readonly log: Logger;
|
|
25
|
+
private readonly dependencyManager: DependencyManager;
|
|
26
|
+
private readonly dependencyResolver: DependencyResolver;
|
|
27
|
+
private readonly fileFinder: FileFinder;
|
|
28
|
+
private readonly moduleGrouper: ModuleGrouper;
|
|
29
|
+
private readonly promptHandler: PromptHandler;
|
|
30
|
+
|
|
31
|
+
constructor(
|
|
32
|
+
private readonly config: OptionsGeneration,
|
|
33
|
+
private readonly registry: NSRegistry,
|
|
34
|
+
) {
|
|
35
|
+
this.log = new Logger(config.verbose, "ModuleLoader");
|
|
36
|
+
this.dependencyManager = DependencyManager.getInstance(config);
|
|
37
|
+
this.dependencyResolver = new DependencyResolver();
|
|
38
|
+
this.fileFinder = new FileFinder(config.girDirectories, this.dependencyManager);
|
|
39
|
+
this.moduleGrouper = new ModuleGrouper();
|
|
40
|
+
this.promptHandler = new PromptHandler(config.verbose);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sets the traverse dependencies for the current girModule,
|
|
45
|
+
* is required so that all dependencies can be found internally when generating the dependency imports for the module .d.ts file
|
|
46
|
+
*/
|
|
47
|
+
private async initGirModules(girModules: GirModuleResolvedBy[]): Promise<void> {
|
|
48
|
+
for (const girModule of girModules) {
|
|
49
|
+
const dependencies = this.dependencyResolver.getTransitiveDependencies(girModule.packageName);
|
|
50
|
+
await girModule.module.initTransitiveDependencies(dependencies);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Reads a gir xml module file and creates an object of GirModule.
|
|
56
|
+
* Also sets the setDependencyMap
|
|
57
|
+
*/
|
|
58
|
+
private async loadAndCreateGirModule(dependency: Dependency): Promise<GirModule | null> {
|
|
59
|
+
if (!dependency.exists || dependency.path === null) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.log.log(`Loading ${dependency.packageName}...`);
|
|
64
|
+
const girModule = await GirModule.load(dependency, this.config, this.registry);
|
|
65
|
+
// Figure out transitive module dependencies
|
|
66
|
+
this.dependencyResolver.extendDependencyMapByGirModule(girModule);
|
|
67
|
+
return girModule;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* If multiple versions of the same module are found, this will ask the user with input prompts for the version they wish to use.
|
|
72
|
+
* Ignores also modules that depend on a module that should be ignored
|
|
73
|
+
*/
|
|
74
|
+
private async askForEachConflictVersionsPrompt(
|
|
75
|
+
girModulesGroupedMap: GirModulesGroupedMap,
|
|
76
|
+
ignore: string[],
|
|
77
|
+
): Promise<{ keep: Set<GirModuleResolvedBy>; ignore: string[] }> {
|
|
78
|
+
let keep = new Set<GirModuleResolvedBy>();
|
|
79
|
+
|
|
80
|
+
for (const girModulesGrouped of Object.values(girModulesGroupedMap)) {
|
|
81
|
+
// Remove ignored modules from group
|
|
82
|
+
girModulesGrouped.modules = girModulesGrouped.modules.filter(
|
|
83
|
+
(girGroup) => !ignore.includes(girGroup.packageName),
|
|
84
|
+
);
|
|
85
|
+
girModulesGrouped.hasConflict = girModulesGrouped.modules.length >= 2;
|
|
86
|
+
|
|
87
|
+
if (girModulesGrouped.modules.length <= 0) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Ask for version if there is a conflict
|
|
92
|
+
if (!girModulesGrouped.hasConflict) {
|
|
93
|
+
keep = union<GirModuleResolvedBy>(keep, girModulesGrouped.modules);
|
|
94
|
+
} else {
|
|
95
|
+
let goBack = true;
|
|
96
|
+
let versionAnswer: AnswerVersion | null = null;
|
|
97
|
+
let ignoreDepsAnswer: "Yes" | "No" | "Go back" | null = null;
|
|
98
|
+
let wouldIgnoreDeps: GirModuleResolvedBy[] = [];
|
|
99
|
+
|
|
100
|
+
while (goBack) {
|
|
101
|
+
versionAnswer = await this.promptHandler.askForVersionsPrompt(girModulesGrouped);
|
|
102
|
+
// Check modules that depend on the unchosen modules
|
|
103
|
+
wouldIgnoreDeps = this.dependencyResolver.findModulesDependingOnPackages(
|
|
104
|
+
girModulesGroupedMap,
|
|
105
|
+
versionAnswer.unselected,
|
|
106
|
+
);
|
|
107
|
+
// Do not check dependencies that have already been ignored
|
|
108
|
+
wouldIgnoreDeps = wouldIgnoreDeps.filter((dep) => !ignore.includes(dep.packageName));
|
|
109
|
+
ignoreDepsAnswer = await this.promptHandler.askIgnoreDepsPrompt(wouldIgnoreDeps);
|
|
110
|
+
goBack = ignoreDepsAnswer === "Go back";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!versionAnswer) {
|
|
114
|
+
throw new Error("Error in processing the prompt versionAnswer");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (ignoreDepsAnswer === "Yes") {
|
|
118
|
+
// Also ignore the dependencies of the unselected version
|
|
119
|
+
ignore = ignore.concat(wouldIgnoreDeps.map((dep) => dep.packageName));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const unionMe = this.moduleGrouper.sortVersionsByAnswer(girModulesGrouped, versionAnswer.selected);
|
|
123
|
+
// Do not ignore the selected package version
|
|
124
|
+
keep = union<GirModuleResolvedBy>(keep, unionMe.keep);
|
|
125
|
+
// Ignore the unchosen package versions
|
|
126
|
+
ignore = ignore.concat(unionMe.ignore);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (ignore && ignore.length > 0) {
|
|
131
|
+
this.promptHandler.showIgnoredModules(ignore);
|
|
132
|
+
await this.promptHandler.askAddToIgnoreToConfigPrompt(ignore);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
keep,
|
|
137
|
+
ignore,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Reads the gir xml module files and creates an object of GirModule for each module
|
|
143
|
+
*/
|
|
144
|
+
private async loadGirModules(
|
|
145
|
+
dependencies: Dependency[],
|
|
146
|
+
ignoreDependencies: string[] = [],
|
|
147
|
+
girModules: GirModuleResolvedBy[] = [],
|
|
148
|
+
resolvedBy = ResolveType.BY_HAND,
|
|
149
|
+
failedGirModules = new Set<string>(),
|
|
150
|
+
): Promise<{ loaded: GirModuleResolvedBy[]; failed: Set<string> }> {
|
|
151
|
+
let newModuleFound = false;
|
|
152
|
+
|
|
153
|
+
// Clone array and filter out ignored dependencies
|
|
154
|
+
dependencies = [...dependencies].filter((dep) => {
|
|
155
|
+
const packageName = dep.packageName;
|
|
156
|
+
return !ignoreDependencies.some((ignored) => {
|
|
157
|
+
// Remove */ prefix if present (e.g., "*/Gtk-4.0" -> "Gtk-4.0")
|
|
158
|
+
const cleanIgnored = ignored.startsWith("*/") ? ignored.slice(2) : ignored;
|
|
159
|
+
return packageName === cleanIgnored;
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
while (dependencies.length > 0) {
|
|
164
|
+
const dependency = dependencies.shift();
|
|
165
|
+
if (!dependency?.packageName) continue;
|
|
166
|
+
// If module has not already been loaded
|
|
167
|
+
if (!this.dependencyResolver.existsGirModules(girModules, dependency.packageName)) {
|
|
168
|
+
const girModule = await this.loadAndCreateGirModule(dependency);
|
|
169
|
+
if (!girModule) {
|
|
170
|
+
if (!failedGirModules.has(dependency.packageName)) {
|
|
171
|
+
// In external-deps mode the strict check after loading turns missing
|
|
172
|
+
// transitive deps into a hard error; suppress the per-dep warn here so
|
|
173
|
+
// the user sees one consolidated error instead of a wall of warnings.
|
|
174
|
+
// `--allow-missing-deps` opts into the same suppression with a soft fail.
|
|
175
|
+
if (!this.config.externalDeps) {
|
|
176
|
+
this.log.warn(WARN_NO_GIR_FILE_FOUND_FOR_PACKAGE(dependency.packageName));
|
|
177
|
+
}
|
|
178
|
+
failedGirModules.add(dependency.packageName);
|
|
179
|
+
}
|
|
180
|
+
} else if (girModule?.packageName) {
|
|
181
|
+
const addModule = {
|
|
182
|
+
namespace: dependency.namespace,
|
|
183
|
+
version: dependency.version,
|
|
184
|
+
packageName: girModule.packageName,
|
|
185
|
+
module: girModule,
|
|
186
|
+
resolvedBy,
|
|
187
|
+
path: dependency.path,
|
|
188
|
+
};
|
|
189
|
+
girModules.push(addModule);
|
|
190
|
+
newModuleFound = true;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (!newModuleFound) {
|
|
196
|
+
return {
|
|
197
|
+
loaded: girModules,
|
|
198
|
+
failed: failedGirModules,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Figure out transitive module dependencies
|
|
203
|
+
await this.initGirModules(girModules);
|
|
204
|
+
|
|
205
|
+
// Load girModules for dependencies
|
|
206
|
+
for (const girModule of girModules) {
|
|
207
|
+
// Load dependencies
|
|
208
|
+
const transitiveDependencies = girModule.module.transitiveDependencies;
|
|
209
|
+
if (transitiveDependencies.length > 0) {
|
|
210
|
+
await this.loadGirModules(
|
|
211
|
+
transitiveDependencies,
|
|
212
|
+
ignoreDependencies,
|
|
213
|
+
girModules,
|
|
214
|
+
ResolveType.DEPENDENCE,
|
|
215
|
+
failedGirModules,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
loaded: girModules,
|
|
222
|
+
failed: failedGirModules,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Loads all found `packageNames`
|
|
228
|
+
* @param packageNames Module names to load
|
|
229
|
+
* @param ignore Modules to ignore
|
|
230
|
+
* @param doNotAskForVersionOnConflict Set this to false if you want to get a prompt for each version conflict
|
|
231
|
+
*/
|
|
232
|
+
public async getModulesResolved(
|
|
233
|
+
packageNames: string[],
|
|
234
|
+
ignore: string[] = [],
|
|
235
|
+
doNotAskForVersionOnConflict = true,
|
|
236
|
+
): Promise<{ keep: GirModuleResolvedBy[]; grouped: GirModulesGroupedMap; ignore: string[]; failed: Set<string> }> {
|
|
237
|
+
const girFiles = await this.fileFinder.findGirFiles([...packageNames], ignore);
|
|
238
|
+
// Always require these because GJS does...
|
|
239
|
+
const GLib = await this.dependencyManager.get("GLib", "2.0");
|
|
240
|
+
const Gio = await this.dependencyManager.get("Gio", "2.0");
|
|
241
|
+
const GObject = await this.dependencyManager.get("GObject", "2.0");
|
|
242
|
+
const Cairo = await this.dependencyManager.get("cairo", "1.0");
|
|
243
|
+
|
|
244
|
+
// Update library versions for GObject and Gio to use GLib's version
|
|
245
|
+
|
|
246
|
+
const dependencies = await this.fileFinder.girFilePathToDependencies(girFiles);
|
|
247
|
+
|
|
248
|
+
// Load GJS force-loads as DEPENDENCE so they are never treated as user-requested
|
|
249
|
+
// modules. This ensures --external-deps mode doesn't emit output files for them.
|
|
250
|
+
const { loaded: forceLoaded, failed: forceFailed } = await this.loadGirModules(
|
|
251
|
+
[GLib, Gio, GObject, Cairo],
|
|
252
|
+
ignore,
|
|
253
|
+
[],
|
|
254
|
+
ResolveType.DEPENDENCE,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
// Load user-requested modules (and their transitive deps) starting from the
|
|
258
|
+
// already-loaded force-load registry so they are not double-loaded.
|
|
259
|
+
const { loaded, failed } = await this.loadGirModules(
|
|
260
|
+
dependencies.filter(
|
|
261
|
+
(dep) =>
|
|
262
|
+
dep.namespace !== "GLib" &&
|
|
263
|
+
dep.namespace !== "Gio" &&
|
|
264
|
+
dep.namespace !== "GObject" &&
|
|
265
|
+
dep.namespace !== "cairo",
|
|
266
|
+
),
|
|
267
|
+
ignore,
|
|
268
|
+
forceLoaded,
|
|
269
|
+
ResolveType.BY_HAND,
|
|
270
|
+
forceFailed,
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
// External-deps mode is strict by default: any transitive dep GIR that couldn't be
|
|
274
|
+
// loaded would silently degrade type quality. The hardcoded GLib/Gio/GObject/cairo
|
|
275
|
+
// force-loads above are exempt (they exist for runtime convenience, not because the
|
|
276
|
+
// input GIR references them).
|
|
277
|
+
if (this.config.externalDeps && !this.config.allowMissingDeps && failed.size > 0) {
|
|
278
|
+
const exempt = new Set(["GLib-2.0", "Gio-2.0", "GObject-2.0", "cairo-1.0"]);
|
|
279
|
+
const critical = Array.from(failed).filter((pkg) => !exempt.has(pkg));
|
|
280
|
+
if (critical.length > 0) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
`Missing GIR files for transitive dependencies in --external-deps mode:\n` +
|
|
283
|
+
critical.map((pkg) => ` - ${pkg}`).join("\n") +
|
|
284
|
+
`\n\nInstall the corresponding -devel packages, add their directories to ` +
|
|
285
|
+
`--girDirectories, or pass --allow-missing-deps to generate anyway ` +
|
|
286
|
+
`(warning: degraded type quality).`,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
let keep: GirModuleResolvedBy[] = [];
|
|
292
|
+
if (doNotAskForVersionOnConflict) {
|
|
293
|
+
keep = loaded;
|
|
294
|
+
} else {
|
|
295
|
+
const girModulesGrouped = this.moduleGrouper.groupGirFiles(loaded);
|
|
296
|
+
const filtered = await this.askForEachConflictVersionsPrompt(girModulesGrouped, ignore);
|
|
297
|
+
keep = Array.from(filtered.keep);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const grouped = this.moduleGrouper.groupGirFiles(keep);
|
|
301
|
+
|
|
302
|
+
return { keep, grouped, ignore, failed };
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Find modules
|
|
307
|
+
* @param modules Module names to find
|
|
308
|
+
* @param ignore Modules to ignore
|
|
309
|
+
*/
|
|
310
|
+
public async getModules(
|
|
311
|
+
modules: string[],
|
|
312
|
+
ignore: string[] = [],
|
|
313
|
+
): Promise<{ grouped: GirModulesGroupedMap; loaded: GirModuleResolvedBy[]; failed: string[] }> {
|
|
314
|
+
const girFiles = await this.fileFinder.findGirFiles(modules, ignore);
|
|
315
|
+
const dependencies = await this.fileFinder.girFilePathToDependencies(girFiles);
|
|
316
|
+
const { loaded, failed } = await this.loadGirModules(dependencies, ignore);
|
|
317
|
+
const grouped = this.moduleGrouper.groupGirFiles(loaded);
|
|
318
|
+
return { grouped, loaded, failed: Array.from(failed) };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Start parsing the gir modules
|
|
323
|
+
*/
|
|
324
|
+
public parse(girModules: GirModuleResolvedBy[]): void {
|
|
325
|
+
for (const girModule of girModules) {
|
|
326
|
+
girModule.module.parse();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
586
329
|
}
|