@ts-for-gir/cli 4.0.0-beta.2 → 4.0.0-beta.21

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.
@@ -2,12 +2,11 @@
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 'tiny-glob'
7
- import { basename } from 'path'
8
- import { readFile } from 'fs/promises'
5
+ import { type Question } from 'inquirer'
6
+ import { select } from '@inquirer/prompts'
7
+ import { glob } from 'glob'
8
+ import { basename, join } from 'path'
9
9
  import { bold } from 'colorette'
10
- import { parser } from '@gi.ts/parser'
11
10
  import {
12
11
  DependencyManager,
13
12
  ResolveType,
@@ -22,7 +21,7 @@ import { Config } from './config.js'
22
21
 
23
22
  import type {
24
23
  GirModulesGroupedMap,
25
- GenerateConfig,
24
+ OptionsGeneration,
26
25
  GirModuleResolvedBy,
27
26
  GirModulesGrouped,
28
27
  DependencyMap,
@@ -35,7 +34,7 @@ export class ModuleLoader {
35
34
  dependencyManager: DependencyManager
36
35
  /** Transitive module dependencies */
37
36
  modDependencyMap: DependencyMap = {}
38
- constructor(protected readonly config: GenerateConfig) {
37
+ constructor(protected readonly config: OptionsGeneration) {
39
38
  this.log = new Logger(config.verbose, 'ModuleLoader')
40
39
  this.dependencyManager = DependencyManager.getInstance(config)
41
40
  }
@@ -109,49 +108,56 @@ export class ModuleLoader {
109
108
  protected generateContinueQuestion(
110
109
  message = `do you want to continue?`,
111
110
  choices = ['Yes', 'Go back'],
112
- ): ListQuestion {
113
- const question: ListQuestion = {
114
- name: 'continue',
111
+ ): { message: string; choices: string[] } {
112
+ return {
115
113
  message,
116
- type: 'list',
117
114
  choices,
118
115
  }
119
- return question
120
116
  }
121
117
 
122
118
  protected generateIgnoreDepsQuestion(
123
119
  message = `Do you want to ignore them too?`,
124
120
  choices = ['Yes', 'No', 'Go back'],
125
- ): ListQuestion {
126
- const question: ListQuestion = {
127
- name: 'continue',
121
+ ): { message: string; choices: string[] } {
122
+ return {
128
123
  message,
129
- type: 'list',
130
124
  choices,
131
125
  }
132
- return question
133
126
  }
134
127
 
135
128
  protected async askIgnoreDepsPrompt(
136
129
  deps: GirModuleResolvedBy[] | Set<GirModuleResolvedBy>,
137
130
  ): Promise<'Yes' | 'No' | 'Go back'> {
138
- let question: ListQuestion<Answers> | null = null
139
131
  const size = (deps as GirModuleResolvedBy[]).length || (deps as Set<GirModuleResolvedBy>).size || 0
132
+
140
133
  if (size > 0) {
134
+ // Show dependencies that would be ignored
141
135
  this.log.log(bold('\nThe following modules have the ignored modules as dependencies:'))
142
136
  for (const dep of deps) {
143
137
  this.log.log(`- ${dep.packageName}`)
144
138
  }
145
139
  this.log.log(bold('\n'))
146
- question = this.generateIgnoreDepsQuestion()
147
- } else {
148
- this.log.log(bold('\nNo dependencies found on the ignored modules'))
149
- question = this.generateContinueQuestion()
140
+
141
+ // Ask if user wants to ignore these dependencies
142
+ return select<'Yes' | 'No' | 'Go back'>({
143
+ message: 'Do you want to ignore them too?',
144
+ choices: [
145
+ { value: 'Yes', name: 'Yes' },
146
+ { value: 'No', name: 'No' },
147
+ { value: 'Go back', name: 'Go back' },
148
+ ],
149
+ })
150
150
  }
151
151
 
152
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
153
- const answer: string = (await inquirer.prompt([question])).continue
154
- return answer as 'Yes' | 'No' | 'Go back'
152
+ // No dependencies found
153
+ this.log.log(bold('\nNo dependencies found on the ignored modules'))
154
+ return select<'Yes' | 'Go back'>({
155
+ message: 'Do you want to continue?',
156
+ choices: [
157
+ { value: 'Yes', name: 'Yes' },
158
+ { value: 'Go back', name: 'Go back' },
159
+ ],
160
+ })
155
161
  }
156
162
 
157
163
  /**
@@ -159,16 +165,16 @@ export class ModuleLoader {
159
165
  * @param girModuleGrouped
160
166
  * @param message
161
167
  */
162
- protected generateModuleVersionQuestion(girModuleGrouped: GirModulesGrouped, message?: string): ListQuestion {
168
+ protected generateModuleVersionQuestion(girModuleGrouped: GirModulesGrouped, message?: string): Question {
163
169
  message = message || `Multiple versions of '${girModuleGrouped.namespace}' found, which one do you want to use?`
164
170
  const choices = ['All', ...girModuleGrouped.modules.map((module) => module.packageName)]
165
- const question: ListQuestion = {
171
+
172
+ return {
166
173
  name: girModuleGrouped.namespace,
167
174
  message,
168
175
  type: 'list',
169
176
  choices,
170
177
  }
171
- return question
172
178
  }
173
179
 
174
180
  /**
@@ -176,7 +182,7 @@ export class ModuleLoader {
176
182
  * @param girModulesGroupedMap
177
183
  * @param packageName
178
184
  */
179
- protected findPackageNamesDependOnPackage(
185
+ protected findGirFilesDependOnPackage(
180
186
  girModulesGroupedMap: GirModulesGroupedMap,
181
187
  packageName: string,
182
188
  ): GirModuleResolvedBy[] {
@@ -201,28 +207,27 @@ export class ModuleLoader {
201
207
  * @param girModulesGroupedMap
202
208
  * @param packageName
203
209
  */
204
- protected findPackageNamesDependOnPackages(
210
+ protected findGirFilesDependOnPackages(
205
211
  girModulesGroupedMap: GirModulesGroupedMap,
206
212
  packageNames: string[],
207
213
  ): GirModuleResolvedBy[] {
208
214
  let girModules: GirModuleResolvedBy[] = []
209
215
  for (const packageName of packageNames) {
210
- girModules = girModules.concat(this.findPackageNamesDependOnPackage(girModulesGroupedMap, packageName))
216
+ girModules = [...girModules, ...this.findGirFilesDependOnPackage(girModulesGroupedMap, packageName)]
211
217
  }
212
218
  return girModules
213
219
  }
214
220
 
215
221
  protected async askForVersionsPrompt(girModulesGrouped: GirModulesGrouped): Promise<AnswerVersion> {
216
- const question = this.generateModuleVersionQuestion(girModulesGrouped)
217
- const choices = question.choices as string[]
218
- if (!choices) {
219
- throw new Error('No valid questions!')
220
- }
221
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
222
- const selected: string = (await inquirer.prompt([question]))[girModulesGrouped.namespace]
223
- if (!selected) {
224
- throw new Error('No valid answer!')
225
- }
222
+ const choices = ['All', ...girModulesGrouped.modules.map((module) => module.packageName)]
223
+
224
+ const selected = await select<string>({
225
+ message: `Multiple versions of '${girModulesGrouped.namespace}' found, which one do you want to use?`,
226
+ choices: choices.map((choice) => ({
227
+ value: choice,
228
+ name: choice,
229
+ })),
230
+ })
226
231
 
227
232
  if (selected === 'All') {
228
233
  return {
@@ -231,10 +236,9 @@ export class ModuleLoader {
231
236
  }
232
237
  }
233
238
 
234
- const unselected = choices.filter((choice) => choice !== selected)
235
239
  return {
236
240
  selected: [selected],
237
- unselected,
241
+ unselected: choices.filter((choice) => choice !== selected && choice !== 'All'),
238
242
  }
239
243
  }
240
244
 
@@ -270,10 +274,7 @@ export class ModuleLoader {
270
274
  while (goBack) {
271
275
  versionAnswer = await this.askForVersionsPrompt(girModulesGrouped)
272
276
  // Check modules that depend on the unchosen modules
273
- wouldIgnoreDeps = this.findPackageNamesDependOnPackages(
274
- girModulesGroupedMap,
275
- versionAnswer.unselected,
276
- )
277
+ wouldIgnoreDeps = this.findGirFilesDependOnPackages(girModulesGroupedMap, versionAnswer.unselected)
277
278
  // Do not check dependencies that have already been ignored
278
279
  wouldIgnoreDeps = wouldIgnoreDeps.filter((dep) => !ignore.includes(dep.packageName))
279
280
  ignoreDepsAnswer = await this.askIgnoreDepsPrompt(wouldIgnoreDeps)
@@ -314,19 +315,15 @@ export class ModuleLoader {
314
315
  * @param ignoredModules
315
316
  */
316
317
  protected async askAddToIgnoreToConfigPrompt(ignoredModules: string[] | Set<string>): Promise<void> {
317
- const questions = [
318
- {
319
- name: 'addToIgnore',
320
- message: `Do you want to add the ignored modules to your config so that you don't need to select them again next time?\n Config path: '${Config.configFilePath}`,
321
- type: 'list',
322
- choices: ['No', 'Yes'],
323
- },
324
- ]
325
-
326
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
327
- const answer: { [name: string]: string } = await inquirer.prompt(questions)
328
-
329
- if (answer.addToIgnore === 'Yes') {
318
+ const shouldAdd = await select<'Yes' | 'No'>({
319
+ message: `Do you want to add the ignored modules to your config so that you don't need to select them again next time?\n Config path: '${Config.configFilePath}'`,
320
+ choices: [
321
+ { value: 'No', name: 'No' },
322
+ { value: 'Yes', name: 'Yes' },
323
+ ],
324
+ })
325
+
326
+ if (shouldAdd === 'Yes') {
330
327
  await Config.addToConfig({
331
328
  ignore: Array.from(ignoredModules),
332
329
  })
@@ -356,7 +353,7 @@ export class ModuleLoader {
356
353
  * @param girModule
357
354
  */
358
355
  protected extendDependencyMapByGirModule(girModule: GirModule): void {
359
- this.modDependencyMap[girModule.packageName] = girModule.dependencies
356
+ this.modDependencyMap[girModule.packageName] = girModule.dependencies!
360
357
  }
361
358
 
362
359
  /**
@@ -364,11 +361,11 @@ export class ModuleLoader {
364
361
  * is required so that all dependencies can be found internally when generating the dependency imports for the module .d.ts file
365
362
  * @param girModules
366
363
  */
367
- protected setTraverseDependenciesForModules(girModules: GirModuleResolvedBy[]): void {
364
+ protected async initGirModules(girModules: GirModuleResolvedBy[]): Promise<void> {
368
365
  for (const girModule of girModules) {
369
366
  const result: { [name: string]: Dependency } = {}
370
367
  this.traverseDependencies(girModule.packageName, result)
371
- girModule.module.transitiveDependencies = Object.values(result)
368
+ await girModule.module.initTransitiveDependencies(Object.values(result))
372
369
  }
373
370
  }
374
371
 
@@ -383,10 +380,8 @@ export class ModuleLoader {
383
380
  return null
384
381
  }
385
382
 
386
- this.log.log(`Parsing ${dependency.path}...`)
387
- const fileContents = await readFile(dependency.path, 'utf8')
388
- const result = parser.parseGir(fileContents)
389
- const girModule = GirModule.load(result, this.config, this.dependencyManager)
383
+ this.log.log(`Loading ${dependency.packageName}...`)
384
+ const girModule = await GirModule.load(dependency, this.config, this.dependencyManager)
390
385
  // Figure out transitive module dependencies
391
386
  this.extendDependencyMapByGirModule(girModule)
392
387
  return girModule
@@ -451,6 +446,7 @@ export class ModuleLoader {
451
446
  packageName: girModule.packageName,
452
447
  module: girModule,
453
448
  resolvedBy,
449
+ path: dependency.path,
454
450
  }
455
451
  girModules.push(addModule)
456
452
  newModuleFound = true
@@ -466,21 +462,13 @@ export class ModuleLoader {
466
462
  }
467
463
 
468
464
  // Figure out transitive module dependencies
469
- this.setTraverseDependenciesForModules(girModules)
465
+ await this.initGirModules(girModules)
470
466
 
471
467
  // Load girModules for dependencies
472
468
  for (const girModule of girModules) {
473
469
  // Load dependencies
474
470
  const transitiveDependencies = girModule.module.transitiveDependencies
475
471
  if (transitiveDependencies.length > 0) {
476
- for (const transitiveDependency of transitiveDependencies) {
477
- if (ignoreDependencies.includes(transitiveDependency.packageName)) {
478
- this.log.warn(
479
- `Load dependency "${transitiveDependency.packageName}" which is in the ignore list, if this should really be ignored also ignore "${girModule.packageName}"`,
480
- )
481
- }
482
- }
483
-
484
472
  await this.loadGirModules(
485
473
  transitiveDependencies,
486
474
  ignoreDependencies,
@@ -490,6 +478,7 @@ export class ModuleLoader {
490
478
  )
491
479
  }
492
480
  }
481
+
493
482
  return {
494
483
  loaded: girModules,
495
484
  failed: failedGirModules,
@@ -501,60 +490,53 @@ export class ModuleLoader {
501
490
  * @param modules
502
491
  * @param ignore
503
492
  */
504
- protected async findPackageNames(modules: string[], ignore: string[] = []): Promise<Set<string>> {
505
- const foundModules = new Set<string>()
506
-
507
- for (let i = 0; i < modules.length; i++) {
508
- if (modules[i]) {
509
- const filename = `${modules[i]}.gir`
510
- let files: string[] = []
511
- for (const girDirectory of this.config.girDirectories) {
512
- try {
513
- files = files.concat(await glob(filename, { cwd: girDirectory }))
514
- } catch (error) {
515
- this.log.warn(`Error on finding "${filename}" in "${girDirectory}"`, error)
516
- }
517
- }
493
+ protected async findGirFiles(globPackageNames: string[], ignore: string[] = []): Promise<Set<string>> {
494
+ const foundFiles = new Set<string>()
518
495
 
519
- let globModules = files.map((file) => basename(file, '.gir'))
520
- // Filter out the ignored modules
521
- globModules = globModules.filter((mod) => {
522
- const isIgnored = ignore.includes(mod)
523
- if (isIgnored) {
524
- this.log.warn(`Ignore ${mod}`)
525
- }
526
- return !isIgnored
527
- })
528
- globModules.forEach((mod) => foundModules.add(mod))
496
+ for (let i = 0; i < globPackageNames.length; i++) {
497
+ if (!globPackageNames[i]) {
498
+ continue
529
499
  }
500
+ const filename = `${globPackageNames[i]}.gir`
501
+ const pattern = this.config.girDirectories.map((girDirectory) => join(girDirectory, filename))
502
+ const ignoreGirs = ignore.map((girDirectory) => girDirectory + '.gir')
503
+ const files = await glob(pattern, { ignore: ignoreGirs })
504
+ files.forEach((file) => foundFiles.add(file))
530
505
  }
531
- return foundModules
506
+
507
+ return foundFiles
532
508
  }
533
509
 
534
- protected packageNamesToDependencies(packageNames: Set<string>): Dependency[] {
535
- return Array.from(packageNames).map((packageName) => {
510
+ protected async girFilePathToDependencies(girFiles: Set<string>): Promise<Dependency[]> {
511
+ const dependencies: Dependency[] = []
512
+ for (const girFile of girFiles) {
513
+ const packageName = basename(girFile, '.gir')
536
514
  const { namespace, version } = splitModuleName(packageName)
537
- return this.dependencyManager.get(namespace, version)
538
- })
515
+ const dep = await this.dependencyManager.get(namespace, version)
516
+ dependencies.push(dep)
517
+ }
518
+
519
+ return dependencies
539
520
  }
540
521
 
541
522
  /**
542
- * Loads all found `packageNames` and sorts out those that the user does not want to use including their dependencies
523
+ * Loads all found `packageNames`
543
524
  * @param girDirectories
544
525
  * @param packageNames
526
+ * @param doNotAskForVersionOnConflict Set this to false if you want to get a prompt for each version conflict
545
527
  */
546
528
  public async getModulesResolved(
547
529
  packageNames: string[],
548
530
  ignore: string[] = [],
549
531
  doNotAskForVersionOnConflict = true,
550
532
  ): Promise<{ keep: GirModuleResolvedBy[]; grouped: GirModulesGroupedMap; ignore: string[]; failed: Set<string> }> {
551
- const foundPackageNames = await this.findPackageNames([...packageNames], ignore)
533
+ const girFiles = await this.findGirFiles([...packageNames], ignore)
552
534
  // Always require these because GJS does...
553
- const GLib = this.dependencyManager.get('GLib', '2.0')
554
- const Gio = this.dependencyManager.get('Gio', '2.0')
555
- const GObject = this.dependencyManager.get('GObject', '2.0')
535
+ const GLib = await this.dependencyManager.get('GLib', '2.0')
536
+ const Gio = await this.dependencyManager.get('Gio', '2.0')
537
+ const GObject = await this.dependencyManager.get('GObject', '2.0')
556
538
 
557
- const dependencies = this.packageNamesToDependencies(foundPackageNames)
539
+ const dependencies = await this.girFilePathToDependencies(girFiles)
558
540
 
559
541
  const { loaded, failed } = await this.loadGirModules(
560
542
  [
@@ -582,7 +564,7 @@ export class ModuleLoader {
582
564
  }
583
565
 
584
566
  /**
585
- * Find modules with the possibility to use wild cards for module names. E.g. `Gtk*` or `'*'`
567
+ * Find modules
586
568
  * @param girDirectories
587
569
  * @param modules
588
570
  */
@@ -590,10 +572,17 @@ export class ModuleLoader {
590
572
  modules: string[],
591
573
  ignore: string[] = [],
592
574
  ): Promise<{ grouped: GirModulesGroupedMap; loaded: GirModuleResolvedBy[]; failed: string[] }> {
593
- const foundPackageNames = await this.findPackageNames(modules, ignore)
594
- const dependencies = this.packageNamesToDependencies(foundPackageNames)
575
+ const girFiles = await this.findGirFiles(modules, ignore)
576
+ const dependencies = await this.girFilePathToDependencies(girFiles)
595
577
  const { loaded, failed } = await this.loadGirModules(dependencies, ignore)
596
578
  const grouped = this.groupGirFiles(loaded)
597
579
  return { grouped, loaded, failed: Array.from(failed) }
598
580
  }
581
+
582
+ /** Start parsing the gir modules */
583
+ public parse(girModules: GirModuleResolvedBy[]): void {
584
+ for (const girModule of girModules) {
585
+ girModule.module.parse()
586
+ }
587
+ }
599
588
  }
package/src/start.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import yargs from 'yargs'
3
3
  import { hideBin } from 'yargs/helpers'
4
4
 
5
- import { generate, list, doc } from './commands/index.js'
5
+ import { generate, list, doc, copy } from './commands/index.js'
6
6
  import { Config } from './config.js'
7
7
 
8
8
  void yargs(hideBin(process.argv))
@@ -11,6 +11,7 @@ void yargs(hideBin(process.argv))
11
11
  .usage(Config.usage)
12
12
  .command(generate.command, generate.description, generate.builder, generate.handler)
13
13
  .command(list.command, list.description, list.builder, list.handler)
14
+ .command(copy.command, copy.description, copy.builder, copy.handler)
14
15
  .command(doc.command, doc.description, doc.builder, doc.handler)
15
16
  .demandCommand(1)
16
17
  .help().argv