@ts-for-gir/cli 4.0.0-beta.24 → 4.0.0-beta.26

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.
Files changed (62) hide show
  1. package/README.md +84 -2
  2. package/bin/ts-for-gir.js +43 -0
  3. package/package.json +30 -36
  4. package/src/commands/analyze.ts +344 -0
  5. package/src/commands/command-builder.ts +30 -0
  6. package/src/commands/copy.ts +71 -76
  7. package/src/commands/doc.ts +58 -46
  8. package/src/commands/generate.ts +97 -77
  9. package/src/commands/index.ts +6 -4
  10. package/src/commands/json.ts +104 -0
  11. package/src/commands/list.ts +81 -90
  12. package/src/config/config-loader.ts +203 -0
  13. package/src/config/config-writer.ts +52 -0
  14. package/src/config/defaults.ts +61 -0
  15. package/src/config/index.ts +8 -0
  16. package/src/config/options.ts +292 -0
  17. package/src/config.ts +3 -456
  18. package/src/formatters/typescript-formatter.ts +24 -0
  19. package/src/generation-handler.ts +122 -67
  20. package/src/index.ts +4 -4
  21. package/src/module-loader/dependency-resolver.ts +100 -0
  22. package/src/module-loader/file-finder.ts +56 -0
  23. package/src/module-loader/index.ts +8 -0
  24. package/src/module-loader/module-grouper.ts +77 -0
  25. package/src/module-loader/prompt-handler.ts +111 -0
  26. package/src/module-loader.ts +280 -580
  27. package/src/start.ts +18 -14
  28. package/src/types/command-args.ts +110 -0
  29. package/src/types/command-definition.ts +15 -0
  30. package/src/types/commands.ts +35 -0
  31. package/src/types/index.ts +15 -0
  32. package/src/types/report-types.ts +34 -0
  33. package/lib/commands/copy.d.ts +0 -12
  34. package/lib/commands/copy.js +0 -78
  35. package/lib/commands/copy.js.map +0 -1
  36. package/lib/commands/doc.d.ts +0 -12
  37. package/lib/commands/doc.js +0 -38
  38. package/lib/commands/doc.js.map +0 -1
  39. package/lib/commands/generate.d.ts +0 -12
  40. package/lib/commands/generate.js +0 -70
  41. package/lib/commands/generate.js.map +0 -1
  42. package/lib/commands/index.d.ts +0 -4
  43. package/lib/commands/index.js +0 -5
  44. package/lib/commands/index.js.map +0 -1
  45. package/lib/commands/list.d.ts +0 -12
  46. package/lib/commands/list.js +0 -79
  47. package/lib/commands/list.js.map +0 -1
  48. package/lib/config.d.ts +0 -108
  49. package/lib/config.js +0 -409
  50. package/lib/config.js.map +0 -1
  51. package/lib/generation-handler.d.ts +0 -10
  52. package/lib/generation-handler.js +0 -48
  53. package/lib/generation-handler.js.map +0 -1
  54. package/lib/index.d.ts +0 -4
  55. package/lib/index.js +0 -5
  56. package/lib/index.js.map +0 -1
  57. package/lib/module-loader.d.ts +0 -154
  58. package/lib/module-loader.js +0 -465
  59. package/lib/module-loader.js.map +0 -1
  60. package/lib/start.d.ts +0 -2
  61. package/lib/start.js +0 -16
  62. package/lib/start.js.map +0 -1
@@ -2,93 +2,88 @@
2
2
  * Everything you need for the `ts-for-gir copy` command is located here
3
3
  */
4
4
 
5
- import { Argv, BuilderCallback } from 'yargs'
6
- import { copyFile, mkdir } from 'fs/promises'
7
- import { basename, join } from 'path'
8
- import { ModuleLoader } from '../module-loader.js'
9
- import { Config } from '../config.js'
10
- import { Logger, ERROR_NO_MODULES_FOUND } from '@ts-for-gir/lib'
5
+ import { copyFile, mkdir } from "node:fs/promises";
6
+ import { basename, join } from "node:path";
7
+ import type { ConfigFlags, GirModuleResolvedBy, UserConfig } from "@ts-for-gir/lib";
8
+ import { APP_NAME, ERROR_NO_MODULES_FOUND, Logger, NSRegistry } from "@ts-for-gir/lib";
9
+ import { copyOptions, getOptionsGeneration, load } from "../config.ts";
10
+ import { ModuleLoader } from "../module-loader.ts";
11
+ import type { CopyCommandArgs } from "../types/index.ts";
12
+ import { createBuilder } from "./command-builder.ts";
11
13
 
12
- import type { ConfigFlags, UserConfig, GirModuleResolvedBy } from '@ts-for-gir/lib'
14
+ const command = "copy [modules..]";
13
15
 
14
- const command = 'copy [modules..]'
16
+ const description = "Scan for *.gir files and copy them to a new directory";
15
17
 
16
- const description = 'Scan for *.gir files and copy them to a new directory'
18
+ const logger = new Logger(false, "CopyCommand");
17
19
 
18
-
19
- const builder: BuilderCallback<any, ConfigFlags> = (yargs: Argv<any>) => {
20
- const optionNames = Object.keys(Config.copyOptions)
21
- for (const optionName of optionNames) {
22
- yargs = yargs.option(optionName, Config.copyOptions[optionName])
23
- }
24
- return yargs.example(examples) as Argv<ConfigFlags>
25
- }
20
+ const examples: ReadonlyArray<[string, string?]> = [
21
+ [`${APP_NAME} copy -o ./gir`, "Copy found *.gir files to ./gir"],
22
+ [
23
+ `${APP_NAME} copy -g /usr/share/gir-1.0 --ignore=Gtk-3.0 xrandr-1.3 -o ./gir`,
24
+ "Copy all found *.gir files in /usr/share/gir-1.0 excluding Gtk-3.0 and xrandr-1.3 to ./gir",
25
+ ],
26
+ ];
27
+
28
+ const builder = createBuilder<CopyCommandArgs>(copyOptions, examples);
26
29
 
27
30
  const copyGirFile = async (config: UserConfig, depModule: GirModuleResolvedBy) => {
28
- if (!depModule.path) {
29
- Logger.danger(`- ${depModule.packageName} not found`)
30
- return
31
- }
32
- if (!config.outdir) {
33
- Logger.error(`outdir not found`)
34
- return
35
- }
36
- const filename = basename(depModule.path)
37
- const dest = join(config.outdir, filename)
38
- if (depModule.path === dest) {
39
- Logger.yellow(`Skip ${depModule.path}`)
40
- return
41
- }
42
- Logger.success(`Copy ${depModule.path}`)
43
- await copyFile(depModule.path, dest)
44
- }
31
+ if (!depModule.path) {
32
+ logger.danger(`- ${depModule.packageName} not found`);
33
+ return;
34
+ }
35
+ if (!config.outdir) {
36
+ logger.error("outdir not found");
37
+ return;
38
+ }
39
+ const filename = basename(depModule.path);
40
+ const dest = join(config.outdir, filename);
41
+ if (depModule.path === dest) {
42
+ logger.yellow(`Skip ${depModule.path}`);
43
+ return;
44
+ }
45
+ logger.success(`Copy ${depModule.path}`);
46
+ await copyFile(depModule.path, dest);
47
+ };
45
48
 
46
-
47
49
  const handler = async (args: ConfigFlags) => {
48
- const config = await Config.load(args)
49
- const generateConfig = Config.getOptionsGeneration(config)
50
- const moduleLoader = new ModuleLoader(generateConfig)
51
- const { grouped, failed } = await moduleLoader.getModules(config.modules, config.ignore)
52
- const moduleGroups = Object.values(grouped)
53
- if (Object.keys(grouped).length === 0) {
54
- return Logger.error(ERROR_NO_MODULES_FOUND(config.girDirectories))
55
- }
50
+ const config = await load(args);
51
+ const generateConfig = getOptionsGeneration(config);
52
+ const registry = new NSRegistry(); // TODO: Use singleton
53
+ const moduleLoader = new ModuleLoader(generateConfig, registry);
54
+ const { grouped, failed } = await moduleLoader.getModules(config.modules, config.ignore);
55
+ const moduleGroups = Object.values(grouped);
56
+ if (Object.keys(grouped).length === 0) {
57
+ return logger.error(ERROR_NO_MODULES_FOUND(config.girDirectories));
58
+ }
56
59
 
57
- if (!config.outdir) {
58
- Logger.error(`outdir not found`)
59
- return
60
- }
60
+ if (!config.outdir) {
61
+ logger.error("outdir not found");
62
+ return;
63
+ }
61
64
 
62
- await mkdir(config.outdir, { recursive: true }).catch((err) => {
63
- Logger.error(`Failed to copy gir files to ${config.outdir}: ${err}`)
64
- })
65
+ await mkdir(config.outdir, { recursive: true }).catch((err) => {
66
+ logger.error(`Failed to copy gir files to ${config.outdir}: ${err}`);
67
+ });
65
68
 
66
- for (const module of moduleGroups) {
67
- for (const mod of module.modules) {
68
- await copyGirFile(config, mod)
69
- }
70
- }
69
+ for (const module of moduleGroups) {
70
+ for (const mod of module.modules) {
71
+ await copyGirFile(config, mod);
72
+ }
73
+ }
71
74
 
72
- if (failed.length > 0) {
73
- Logger.danger('\nDependencies not found:')
74
- for (const fail of failed) {
75
- Logger.white(`- ${fail}`)
76
- }
77
- }
78
- }
79
-
80
- const examples: ReadonlyArray<[string, string?]> = [
81
- [`${Config.appName} copy -o ./gir`, `Copy found *.gir files to ./gir`],
82
- [
83
- `${Config.appName} copy -g /usr/share/gir-1.0 --ignore=Gtk-3.0 xrandr-1.3 -o ./gir`,
84
- 'Copy all found *.gir files in /usr/share/gir-1.0 excluding Gtk-3.0 and xrandr-1.3 to ./gir',
85
- ],
86
- ]
75
+ if (failed.length > 0) {
76
+ logger.danger("\nDependencies not found:");
77
+ for (const fail of failed) {
78
+ logger.white(`- ${fail}`);
79
+ }
80
+ }
81
+ };
87
82
 
88
83
  export const copy = {
89
- command,
90
- description,
91
- builder,
92
- handler,
93
- examples,
94
- }
84
+ command,
85
+ description,
86
+ builder,
87
+ handler,
88
+ examples,
89
+ };
@@ -2,57 +2,69 @@
2
2
  * Everything you need for the `ts-for-gir generate` command is located here
3
3
  */
4
4
 
5
- import { Argv, BuilderCallback } from 'yargs'
6
- import { Logger, ERROR_NO_MODULES_FOUND } from '@ts-for-gir/lib'
7
- import { GeneratorType } from '@ts-for-gir/generator-base'
8
- import { GenerationHandler } from '../generation-handler.js'
9
- import { Config } from '../config.js'
10
- import { ModuleLoader } from '../module-loader.js'
5
+ import { GeneratorType } from "@ts-for-gir/generator-base";
6
+ import type { ConfigFlags } from "@ts-for-gir/lib";
7
+ import {
8
+ configureConflictsReporter,
9
+ ERROR_NO_MODULES_FOUND,
10
+ type GirModule,
11
+ Logger,
12
+ NSRegistry,
13
+ TypeIdentifier,
14
+ } from "@ts-for-gir/lib";
15
+ import type { Argv, BuilderCallback } from "yargs";
16
+ import { docOptions, getOptionsGeneration, load } from "../config.ts";
17
+ import { GenerationHandler } from "../generation-handler.ts";
18
+ import { ModuleLoader } from "../module-loader.ts";
19
+ import type { DocCommandArgs } from "../types/index.ts";
11
20
 
12
- import type { ConfigFlags } from '@ts-for-gir/lib'
21
+ const command = "doc [modules..]";
13
22
 
14
- const command = 'doc [modules..]'
23
+ const description = "The HTML documentation generator is not yet implemented, but feel free to implement it 🤗";
15
24
 
16
- const description = 'The HTML documentation generator is not yet implemented, but feel free to implement it 🤗'
25
+ const logger = new Logger(false, "DocCommand");
17
26
 
18
-
19
- const builder: BuilderCallback<any, ConfigFlags> = (yargs: Argv<any>) => {
20
- const optionNames = Object.keys(Config.docOptions)
21
- for (const optionName of optionNames) {
22
- yargs = yargs.option(optionName, Config.docOptions[optionName])
23
- }
24
- return yargs.example(examples) as Argv<ConfigFlags>
25
- }
27
+ const builder: BuilderCallback<DocCommandArgs, ConfigFlags> = (yargs: Argv<DocCommandArgs>) => {
28
+ const optionNames = Object.keys(docOptions);
29
+ for (const optionName of optionNames) {
30
+ yargs = yargs.option(optionName, docOptions[optionName]);
31
+ }
32
+ return yargs.example(examples) as Argv<ConfigFlags>;
33
+ };
26
34
 
27
-
28
35
  const handler = async (args: ConfigFlags) => {
29
- const config = await Config.load(args)
30
-
31
- const generateConfig = Config.getOptionsGeneration(config)
32
- const moduleLoader = new ModuleLoader(generateConfig)
33
- const { keep } = await moduleLoader.getModulesResolved(
34
- config.modules,
35
- config.ignore || [],
36
- config.ignoreVersionConflicts,
37
- )
38
- if (keep.length === 0) {
39
- return Logger.error(ERROR_NO_MODULES_FOUND(config.girDirectories))
40
- }
41
- const tsForGir = new GenerationHandler(generateConfig, GeneratorType.HTML_DOC)
42
- const registry = moduleLoader.dependencyManager
43
-
44
- await tsForGir.start(
45
- Array.from(keep).map((girModuleResolvedBy) => girModuleResolvedBy.module),
46
- registry,
47
- )
48
- }
49
-
50
- const examples: ReadonlyArray<[string, string?]> = []
36
+ const config = await load(args);
37
+
38
+ const generateConfig = getOptionsGeneration(config);
39
+ const registry = new NSRegistry(); // TODO: Use singleton
40
+
41
+ // Configure reporters BEFORE parsing to capture all problems
42
+ if (generateConfig.reporter) {
43
+ TypeIdentifier.configureReporter(generateConfig.reporter, generateConfig.reporterOutput);
44
+ configureConflictsReporter(generateConfig.reporter, generateConfig.reporterOutput);
45
+ }
46
+
47
+ const moduleLoader = new ModuleLoader(generateConfig, registry);
48
+ const { keep } = await moduleLoader.getModulesResolved(
49
+ config.modules,
50
+ config.ignore || [],
51
+ config.ignoreVersionConflicts,
52
+ );
53
+ if (keep.length === 0) {
54
+ logger.error(ERROR_NO_MODULES_FOUND(config.girDirectories));
55
+ return;
56
+ }
57
+ const tsForGir = new GenerationHandler(generateConfig, GeneratorType.HTML_DOC, registry);
58
+
59
+ await tsForGir.start(Array.from(keep).map((girModuleResolvedBy) => girModuleResolvedBy.module as GirModule));
60
+ };
61
+
62
+ const examples: ReadonlyArray<[string, string?]> = [];
51
63
 
52
64
  export const doc = {
53
- command,
54
- description,
55
- builder,
56
- handler,
57
- examples,
58
- }
65
+ command,
66
+ description,
67
+ builder,
68
+ handler,
69
+ examples,
70
+ };
@@ -2,90 +2,110 @@
2
2
  * Everything you need for the `ts-for-gir generate` command is located here
3
3
  */
4
4
 
5
- import { Argv, BuilderCallback } from 'yargs'
6
- import { ERROR_NO_MODULES_FOUND, Logger } from '@ts-for-gir/lib'
7
- import { GeneratorType } from '@ts-for-gir/generator-base'
8
- import { GenerationHandler } from '../generation-handler.js'
9
- import { Config } from '../config.js'
10
- import { ModuleLoader } from '../module-loader.js'
11
- import prettier from 'prettier'
12
-
13
- import type { ConfigFlags } from '@ts-for-gir/lib'
14
- import { Formatter } from '@ts-for-gir/lib'
15
-
16
- const command = 'generate [modules..]'
17
-
18
- const description = 'Generates Typescript type definition .d.ts files from GIR for GJS'
19
-
20
-
21
- const builder: BuilderCallback<any, ConfigFlags> = (yargs: Argv<any>) => {
22
- const optionNames = Object.keys(Config.generateOptions)
23
- for (const optionName of optionNames) {
24
- yargs = yargs.option(optionName, Config.generateOptions[optionName])
25
- }
26
- return yargs.example(examples) as Argv<ConfigFlags>
27
- }
28
-
29
-
5
+ import { GeneratorType } from "@ts-for-gir/generator-base";
6
+ import type { ConfigFlags } from "@ts-for-gir/lib";
7
+ import {
8
+ APP_NAME,
9
+ configureConflictsReporter,
10
+ ERROR_NO_MODULES_FOUND,
11
+ type GirModule,
12
+ Logger,
13
+ NSRegistry,
14
+ ReporterService,
15
+ TypeIdentifier,
16
+ } from "@ts-for-gir/lib";
17
+ import { generateOptions, getOptionsGeneration, load } from "../config.ts";
18
+ import { TypeScriptFormatter } from "../formatters/typescript-formatter.ts";
19
+ import { GenerationHandler } from "../generation-handler.ts";
20
+ import { ModuleLoader } from "../module-loader.ts";
21
+ import type { GenerateCommandArgs } from "../types/index.ts";
22
+ import { createBuilder } from "./command-builder.ts";
23
+
24
+ const command = "generate [modules..]";
25
+
26
+ const description = "Generates Typescript type definition .d.ts files from GIR for GJS";
27
+
28
+ const logger = new Logger(false, "GenerateCommand");
29
+
30
+ const examples: ReadonlyArray<[string, string?]> = [
31
+ [
32
+ `${APP_NAME} generate`,
33
+ `Run '${APP_NAME} generate' in your gjs project to generate typings for your project, pass the gir modules you need for your project`,
34
+ ],
35
+ [`${APP_NAME} generate Gtk*`, "You can also use wild cards"],
36
+ [`${APP_NAME} generate '*'`, "If you want to parse all of your locally installed gir modules run"],
37
+ [`${APP_NAME} generate --configName='.ts-for-gir.gtk4.rc.js`, "Use a special config file"],
38
+ [`${APP_NAME} generate --ignore=Gtk-4.0 xrandr-1.3`, "Generate .d.ts. files but not for Gtk-4.0 and xrandr-1.3"],
39
+ ];
40
+
41
+ const builder = createBuilder<GenerateCommandArgs>(generateOptions, examples);
42
+
30
43
  const handler = async (args: ConfigFlags) => {
31
- const config = await Config.load(args)
44
+ const config = await load(args);
32
45
 
33
- const generateConfig = Config.getOptionsGeneration(config)
34
- const moduleLoader = new ModuleLoader(generateConfig)
35
- const { keep } = await moduleLoader.getModulesResolved(
36
- config.modules,
37
- config.ignore || [],
38
- config.ignoreVersionConflicts,
39
- )
46
+ const generateConfig = getOptionsGeneration(config);
47
+ const registry = new NSRegistry(); // TODO: Use singleton
40
48
 
41
- if (keep.length === 0) {
42
- return Logger.error(ERROR_NO_MODULES_FOUND(config.girDirectories))
43
- }
49
+ // Register TypeScript formatter for .d.ts files
50
+ registry.registerFormatter("dts", new TypeScriptFormatter());
44
51
 
45
- moduleLoader.parse(keep)
52
+ const moduleLoader = new ModuleLoader(generateConfig, registry);
46
53
 
47
- const tsForGir = new GenerationHandler(generateConfig, GeneratorType.TYPES)
54
+ // Configure reporters BEFORE parsing to capture all problems
55
+ if (generateConfig.reporter) {
56
+ TypeIdentifier.configureReporter(generateConfig.reporter, generateConfig.reporterOutput);
57
+ configureConflictsReporter(generateConfig.reporter, generateConfig.reporterOutput);
58
+ }
48
59
 
49
- const girModules = Array.from(keep).map((girModuleResolvedBy) => girModuleResolvedBy.module)
60
+ let tsForGir: GenerationHandler | null = null;
50
61
 
51
- moduleLoader.dependencyManager.registerFormatter('dts', new TypeScriptFormatter())
52
- await tsForGir.start(girModules, moduleLoader.dependencyManager)
53
- }
62
+ try {
63
+ const { keep } = await moduleLoader.getModulesResolved(
64
+ config.modules,
65
+ config.ignore || [],
66
+ config.ignoreVersionConflicts,
67
+ );
54
68
 
55
- const examples: ReadonlyArray<[string, string?]> = [
56
- [
57
- `${Config.appName} generate`,
58
- `Run '${Config.appName} generate' in your gjs project to generate typings for your project, pass the gir modules you need for your project`,
59
- ],
60
- [`${Config.appName} generate Gtk*`, 'You can also use wild cards'],
61
- [`${Config.appName} generate '*'`, 'If you want to parse all of your locally installed gir modules run'],
62
- [`${Config.appName} generate --configName='.ts-for-gir.gtk4.rc.js`, 'Use a special config file'],
63
- [
64
- `${Config.appName} generate --ignore=Gtk-4.0 xrandr-1.3`,
65
- 'Generate .d.ts. files but not for Gtk-4.0 and xrandr-1.3',
66
- ],
67
- ]
68
-
69
- class TypeScriptFormatter extends Formatter {
70
- format(input: string): Promise<string> {
71
- try {
72
- return prettier.format(input, {
73
- singleQuote: true,
74
- parser: 'typescript',
75
- printWidth: 120,
76
- tabWidth: 4,
77
- })
78
- } catch (error) {
79
- Logger.warn('[TypeScriptFormatter] Failed to format with prettier, returning original input', error)
80
- return Promise.resolve(input)
81
- }
82
- }
83
- }
69
+ if (keep.length === 0) {
70
+ logger.error(ERROR_NO_MODULES_FOUND(config.girDirectories));
71
+ return;
72
+ }
73
+
74
+ moduleLoader.parse(keep);
75
+
76
+ tsForGir = new GenerationHandler(generateConfig, GeneratorType.TYPES, registry);
77
+
78
+ const girModules = Array.from(keep).map((girModuleResolvedBy) => girModuleResolvedBy.module as GirModule);
79
+
80
+ await tsForGir.start(girModules);
81
+ } catch (error) {
82
+ // If reporter is enabled and tsForGir was created, make sure the report is generated
83
+ if (generateConfig.reporter && tsForGir) {
84
+ const service = ReporterService.getInstance();
85
+
86
+ // Log the error to the reporter
87
+ if (tsForGir.log) {
88
+ tsForGir.log.reportGenerationFailure(
89
+ "Main",
90
+ error instanceof Error ? error : new Error(String(error)),
91
+ "Generation failed",
92
+ );
93
+ }
94
+
95
+ // Generate and save the report
96
+ await service.printComprehensiveSummary();
97
+ await service.saveComprehensiveReport();
98
+ }
99
+
100
+ // Re-throw the error to maintain existing behavior
101
+ throw error;
102
+ }
103
+ };
84
104
 
85
105
  export const generate = {
86
- command,
87
- description,
88
- builder,
89
- handler,
90
- examples,
91
- }
106
+ command,
107
+ description,
108
+ builder,
109
+ handler,
110
+ examples,
111
+ };
@@ -1,4 +1,6 @@
1
- export * from './copy.js'
2
- export * from './doc.js'
3
- export * from './generate.js'
4
- export * from './list.js'
1
+ export * from "./analyze.ts";
2
+ export * from "./copy.ts";
3
+ export * from "./doc.ts";
4
+ export * from "./generate.ts";
5
+ export * from "./json.ts";
6
+ export * from "./list.ts";
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Everything you need for the `ts-for-gir json` command is located here
3
+ */
4
+
5
+ import { GeneratorType } from "@ts-for-gir/generator-base";
6
+ import type { ConfigFlags } from "@ts-for-gir/lib";
7
+ import {
8
+ APP_NAME,
9
+ configureConflictsReporter,
10
+ ERROR_NO_MODULES_FOUND,
11
+ type GirModule,
12
+ Logger,
13
+ NSRegistry,
14
+ ReporterService,
15
+ TypeIdentifier,
16
+ } from "@ts-for-gir/lib";
17
+ import { generateOptions, getOptionsGeneration, load } from "../config.ts";
18
+ import { GenerationHandler } from "../generation-handler.ts";
19
+ import { ModuleLoader } from "../module-loader.ts";
20
+ import type { GenerateCommandArgs } from "../types/index.ts";
21
+ import { createBuilder } from "./command-builder.ts";
22
+
23
+ const command = "json [modules..]";
24
+
25
+ const description = "Generates JSON representation from GIR files for analysis and tooling";
26
+
27
+ const logger = new Logger(false, "JsonCommand");
28
+
29
+ const examples: ReadonlyArray<[string, string?]> = [
30
+ [`${APP_NAME} json`, `Run '${APP_NAME} json' in your gjs project to generate JSON files for your project`],
31
+ [`${APP_NAME} json Gtk*`, "You can also use wild cards"],
32
+ [`${APP_NAME} json '*'`, "If you want to parse all of your locally installed gir modules run"],
33
+ [`${APP_NAME} json --configName='.ts-for-gir.gtk4.rc.js`, "Use a special config file"],
34
+ [`${APP_NAME} json --ignore=Gtk-4.0 xrandr-1.3`, "Generate JSON files but not for Gtk-4.0 and xrandr-1.3"],
35
+ ];
36
+
37
+ const builder = createBuilder<GenerateCommandArgs>(generateOptions, examples);
38
+
39
+ const handler = async (args: ConfigFlags) => {
40
+ const config = await load(args);
41
+
42
+ const generateConfig = getOptionsGeneration(config);
43
+ const registry = new NSRegistry(); // TODO: Use singleton
44
+
45
+ const moduleLoader = new ModuleLoader(generateConfig, registry);
46
+
47
+ // Configure reporters BEFORE parsing to capture all problems
48
+ if (generateConfig.reporter) {
49
+ TypeIdentifier.configureReporter(generateConfig.reporter, generateConfig.reporterOutput);
50
+ configureConflictsReporter(generateConfig.reporter, generateConfig.reporterOutput);
51
+ }
52
+
53
+ let tsForGir: GenerationHandler | null = null;
54
+
55
+ try {
56
+ const { keep } = await moduleLoader.getModulesResolved(
57
+ config.modules,
58
+ config.ignore || [],
59
+ config.ignoreVersionConflicts,
60
+ );
61
+
62
+ if (keep.length === 0) {
63
+ logger.error(ERROR_NO_MODULES_FOUND(config.girDirectories));
64
+ return;
65
+ }
66
+
67
+ moduleLoader.parse(keep);
68
+
69
+ tsForGir = new GenerationHandler(generateConfig, GeneratorType.JSON, registry);
70
+
71
+ const girModules = Array.from(keep).map((girModuleResolvedBy) => girModuleResolvedBy.module as GirModule);
72
+
73
+ await tsForGir.start(girModules);
74
+ } catch (error) {
75
+ // If reporter is enabled and tsForGir was created, make sure the report is generated
76
+ if (generateConfig.reporter && tsForGir) {
77
+ const service = ReporterService.getInstance();
78
+
79
+ // Log the error to the reporter
80
+ if (tsForGir.log) {
81
+ tsForGir.log.reportGenerationFailure(
82
+ "Main",
83
+ error instanceof Error ? error : new Error(String(error)),
84
+ "JSON generation failed",
85
+ );
86
+ }
87
+
88
+ // Generate and save the report
89
+ await service.printComprehensiveSummary();
90
+ await service.saveComprehensiveReport();
91
+ }
92
+
93
+ // Re-throw the error to maintain existing behavior
94
+ throw error;
95
+ }
96
+ };
97
+
98
+ export const json = {
99
+ command,
100
+ description,
101
+ builder,
102
+ handler,
103
+ examples,
104
+ };